package thread.blocking.demo;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;

public class BlockingHashMap <K, V>{
    //ConcurrentHashMap 本身是线程安全的
    private final ConcurrentHashMap<K, BlockingQueue<V>> map;

    public BlockingHashMap() {
        this.map = new ConcurrentHashMap<>();
    }

    //插入元素
    public  void  put (K key,V value){
        /**
         * 1.computeIfAbsent 方法在键不存在于 map 或者与键关联的值为 null 时，
         *  使用给定的映射函数计算值，并将其添加到 map 中。
         * 2.如果键已经存在于 map 中并且与之关联的值非空，computeIfAbsent返回该非空值
         * 3.这里如果没有此键，那么创建，如果有则返回原值。
         */
        BlockingQueue<V> queue = map.computeIfAbsent(key, k -> new LinkedBlockingQueue<>());
        queue.add(value);
    }

    //与put同理
    //获取元素时，如果不存在则阻塞
    public V take(K key) throws InterruptedException {
        BlockingQueue<V> queue = map.computeIfAbsent(key, k -> new LinkedBlockingQueue<>());
        return queue.take();
    }

    //移除元素
    public boolean remove(K key){
        if(this.map.containsKey(key)){
            this.map.remove(key);
            return true;
        }
        return false;
    }

    @Override
    public String toString() {
        String result = "{";
        for (K k : this.map.keySet()){
            result += k.toString()+"=";
            result += this.map.get(k).toString()+",";
        }
        result = result.substring(0,result.length()-1);
        result+="}";
        return result;
    }
}
